#include"sync.h"
#include"asm_utils.h"
#include"stdio.h"
#include"os_modules.h"
#include"program.h"

SpinLock::SpinLock()
{
    initialize();
}
void SpinLock::initialize()
{
    bolt = 0;
}
void SpinLock::lock()
{
    uint32 key = 1;
    do
    {
       asm_atomic_exchange(&key,&bolt);
       __asm__ __volatile__("pause");
    //    printf("pid: %d\n",programManager.running->pid);
    } while (key);
}
void SpinLock::unlock()
{
    bolt = 0;
}

Semaphore::Semaphore()
{
    initialize(0);
}
void Semaphore::initialize(uint32 counter)
{
    this->counter = counter;
    semLock.initialize();
    waiting.initialize();
}
void Semaphore::P()
{
    PCB* cur = nullptr;
    while(true)
    {
        semLock.lock();
        if(counter>0)
        {
           counter--;
           semLock.unlock(); 
           return;
        }
        cur = programManager.running;
        waiting.push_back(&(cur->tagInGeneralList));
        cur->status = ProgramStatus::BLOCKED;
        
        semLock.unlock();
        programManager.schedule_multilevel_feedback_queue();
    }
}
void Semaphore::V()
{
    semLock.lock();
    counter++;
    if(waiting.size())
    {
        PCB* program = ListItemToPCB(waiting.front(),tagInGeneralList);
        waiting.pop_front();
        semLock.unlock();
        programManager.MESA_WakeUp(program);
        // programManager.Hasen_WakeUp(program);
        // programManager.Hoare_WakeUp(program);
    }else{
        semLock.unlock();
    }
}

ReaderWriter::ReaderWriter()
{
    initialize();
}
void ReaderWriter::initialize(uint32 counter)
{
    resourceAccess.initialize(counter);
    readerCountAccess.initialize(1);
    readerCount=0;
}
void ReaderWriter::readerEnter()
{
    readerCountAccess.P();
    if(readerCount==0){
        resourceAccess.P(); //没有读者时才申请资源
    }
    readerCount++;
    readerCountAccess.V();
}
void ReaderWriter::readerExit()
{
    readerCountAccess.P();
    readerCount--;
    if(readerCount==0){
        resourceAccess.V();
    }
    readerCountAccess.V();
}
void ReaderWriter::writerEnter()
{
    resourceAccess.P();
}
void ReaderWriter::writerExit()
{
    resourceAccess.V();
}